package com.zhouyu.redisExample.redission;

import lombok.extern.log4j.Log4j2;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Log4j2
@Service
public class RedissionService {

    @Autowired
    RedissonClient redisson;

    public <T> T get(String key, Class<T> tClass) {
        RBucket<Object> bucket = redisson.getBucket(key);
        if (bucket != null) {
            Object obj = bucket.get();
            return tClass.cast(obj);
        }
        return null;
    }

    public <T> boolean set(String key,T t){
        RBucket<Object> bucket = redisson.getBucket(key);
        if(bucket==null){
           return bucket.trySet(t);
        }
        return false;
    }

    public <T> boolean setExpire(String key,T t,long time,TimeUnit timeUnit){
        RBucket<Object> bucket = redisson.getBucket(key);
        if(bucket==null){
            return bucket.trySet(t,time, timeUnit);
        }
        return false;
    }

    public long incre(String key,long initValue){
        RLongAdder atomicLong  = redisson.getLongAdder(key);
        atomicLong.add(initValue);
        atomicLong.increment();
        return atomicLong.sum();
    }

    public long decre(String key,long initValue){
        RLongAdder atomicLong  = redisson.getLongAdder(key);
        atomicLong.add(initValue);
        atomicLong.decrement();
        return atomicLong.sum();
    }

    public void destroyIncre(String key){
        RLongAdder atomicLong  = redisson.getLongAdder(key);
        atomicLong.destroy();
    }

    public List<String> getKeysPattern(String regx){
        ArrayList<String> keylist = new ArrayList<>();
        RKeys keys = redisson.getKeys();
        Iterable<String> iterable;
        if(regx==null){
            iterable=keys.getKeys();
        }else {
            iterable= keys.getKeysByPattern(regx);
        }
        for (String key : iterable) {
            keylist.add(key);
        }
        return keylist;
    }

    public<T> Map<String,T> getMap(String key,Class<T> tClass){
        HashMap<String, T> newMap = new HashMap<>();
        RMap<String, Object> map = redisson.getMapCache(key);
        Set<Map.Entry<String, Object>> entries = map.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            Object value = entry.getValue();
            if(value!=null){
                T t = tClass.cast(value);
                newMap.put(entry.getKey(),t);
            }
        }
        return newMap;
    }

    public<T> Map<String,T> addMapKV(String key1,String key2,T t){
        RMap<String, T> map = redisson.getMapCache(key1);
        map.putIfAbsent(key2,t);
        return map;
    }

    public<T> void addMapKV(String key1,Map<String,T> map){
        RMap<String, T> rmap = redisson.getMapCache(key1);
        rmap.putAll(map);
    }

    public<T> void addMapExpireKV(String key1,String key2,T t,long time,TimeUnit timeUnit){
        RMapCache<String, Object> mapCache = redisson.getMapCache(key1);
        mapCache.put(key2,t,time,timeUnit,10, TimeUnit.SECONDS);
    }

    public Map<String, Object> removeMapKV(String key1, String key2){
        RMap<String, Object> map = redisson.getMapCache(key1);
        map.remove(key2);
        return map;
    }

    public void clearMap(String key1){
        RMap<Object, Object> map = redisson.getMapCache(key1);
        map.clear();
    }

    public<T> boolean addSet(String key,T t){
        RSetCache<T> setCache = redisson.getSetCache(key);
        return setCache.add(t);
    }

    public<T> Set<T> readSets(String key,Class<T> tClass){
        HashSet<T> set = null;
        try {
            set = new HashSet<>();
            RSetCache<Object> setCache = redisson.getSetCache(key);
            Set<Object> objects = setCache.readAll();
            for (Object object : objects) {
                T t = tClass.cast(object);
                set.add(t);
            }
        } catch (Exception e) {
            log.error("get set error,msg:{}",e.getMessage());
            throw new RuntimeException("get set error");
        }
        return set;
    }

    public<T> boolean addSetExpire(String key,T t,long time,TimeUnit timeUnit){
        RSetCache<T> setCache = redisson.getSetCache(key);
        return setCache.add(t,time,timeUnit);
    }

    public<T> boolean addSetScore(String key,double score,T t){
        RScoredSortedSet<Object> scoredSortedSet = redisson.getScoredSortedSet(key);
        return scoredSortedSet.add(score,t);
    }

    public Set<Object> setRange(String key, int start, int end){
        HashSet<Object> sets = new HashSet<>();
        RScoredSortedSet<Object> scoredSortedSet = redisson.getScoredSortedSet(key);
        Collection<Object> collection = scoredSortedSet.valueRange(start, end);
        Object[] objects = collection.toArray();
        for (Object object : objects) {
            sets.add(object);
        }
        return sets;
    }

    public<T> void addList(String key,T t){
        RList<T> list = redisson.getList(key);
        list.add(t);
    }

    public<T> List<T> readList(String key,Class<T> tclass){
        ArrayList<T> arrayList = new ArrayList<>();
        RList<Object> list = redisson.getList(key);
        for (Object o : list) {
            T cast = tclass.cast(o);
            arrayList.add(cast);
        }
        return arrayList;
    }


}